from odoo.exceptions import UserError
from odoo.addons.basic_configuration.functions.rp_pay_interface import RpPayInterface
from functional import seq


class RpFinanceRelatedFunc(object):
    """
    Description:
    满足一切涉及到财务相关的逻辑
    """

    def __init__(self, env):
        self.env = env

    def update_payment(self, rp_ship_order_id, rp_ship_order_payment_id, balance_tag, stripe_tag, balance_price, stripe_price, order_total_price):
        """
        更新支付单
        """
        # 分项采用四舍五入方式
        mail_route_actual_price = round(rp_ship_order_id.mail_route_actual_price, 2)  # 邮路
        fulfillment_actual_price = round(rp_ship_order_id.fulfillment_total_actual_price, 2)  # 头尾程
        value_added_actual_price = round(rp_ship_order_id.value_added_total_actual_price, 2)  # 增值服务
        if balance_tag and stripe_tag:
            pay_method = 'union'
        elif balance_tag:
            pay_method = 'balance'
        else:
            pay_method = 'stripe'
        # 基本信息填充
        basic_values = {
            'pay_method': pay_method,
            'state': 'not_pay',
            'total_balance_price': balance_price,
            'total_stripe_price': stripe_price
        }
        rp_ship_order_payment_id.sudo().write(basic_values)
        # 余额支付总金额和Stripe支付总金额
        total_balance_price = rp_ship_order_payment_id.total_balance_price
        total_stripe_price = rp_ship_order_payment_id.total_stripe_price
        # 支付单明细填充
        # 组合支付
        if pay_method == 'union':
            stripe_radio = round(stripe_price / order_total_price, 4)
            balance_radio = round(balance_price / order_total_price, 4)
            values = [
                # 任何精度问题由邮路补偿
                {
                    'stripe_price': total_stripe_price - round(fulfillment_actual_price * stripe_radio, 2) - round(value_added_actual_price * stripe_radio, 2),
                    'tax_price': (total_stripe_price - round(fulfillment_actual_price * stripe_radio, 2) - round(value_added_actual_price * stripe_radio, 2)) * 0.1,
                    'balance_price': total_balance_price - round(fulfillment_actual_price * balance_radio, 2) - round(value_added_actual_price * balance_radio, 2),
                    'description': "邮路名称：{}[{}]".format(rp_ship_order_id.shipper_mail_route_id.name, rp_ship_order_id.shipper_mail_route_id.code),
                    'type': 'mail_route'
                },
                {
                    'stripe_price': round(fulfillment_actual_price * stripe_radio, 2),
                    'tax_price': round(fulfillment_actual_price * stripe_radio, 2) * 0.1,
                    'balance_price': round(fulfillment_actual_price * balance_radio, 2),
                    'description': "头尾程：{}".format('-'.join(rp_ship_order_id.rp_ship_order_fulfillment_line_ids.mapped(lambda r: r.name))),
                    'type': 'fulfillment'
                },
                {
                    'stripe_price': round(value_added_actual_price * stripe_radio, 2),
                    'tax_price': round(value_added_actual_price * stripe_radio, 2) * 0.1,
                    'balance_price': round(value_added_actual_price * balance_radio, 2),
                    'description': "增值服务：{}".format('-'.join(rp_ship_order_id.rp_ship_order_value_added_line_ids.mapped(lambda r: r.value_added_id.name))),
                    'type': 'value_added'
                }
            ]
            # 清除旧纪录
            rp_ship_order_payment_id.sudo().write({'rp_payment_line_ids': [(5, 0, 0)]})
            rp_ship_order_payment_id.sudo().write({'rp_payment_line_ids': [(0, 0, value) for value in values]})
        if pay_method == 'balance':
            values = [
                {
                    'balance_price': mail_route_actual_price,
                    'description': "邮路名称：{}[{}]".format(rp_ship_order_id.shipper_mail_route_id.name, rp_ship_order_id.shipper_mail_route_id.code),
                    'type': 'mail_route'
                },
                {
                    'balance_price': fulfillment_actual_price,
                    'description': "头尾程：{}".format('-'.join(rp_ship_order_id.rp_ship_order_fulfillment_line_ids.mapped(lambda r: r.name))),
                    'type': 'fulfillment'
                },
                {
                    'balance_price': value_added_actual_price,
                    'description': "增值服务：{}".format('-'.join(rp_ship_order_id.rp_ship_order_value_added_line_ids.mapped(lambda r: r.value_added_id.name))),
                    'type': 'value_added'
                }
            ]
            rp_ship_order_payment_id.sudo().write({'rp_payment_line_ids': [(5, 0, 0)]})
            rp_ship_order_payment_id.sudo().write({'rp_payment_line_ids': [(0, 0, value) for value in values]})
        if pay_method == 'stripe':
            values = [
                {
                    'stripe_price': mail_route_actual_price,
                    'tax_price': mail_route_actual_price * 0.1,
                    'description': "邮路名称：{}[{}]".format(rp_ship_order_id.shipper_mail_route_id.name, rp_ship_order_id.shipper_mail_route_id.code),
                    'type': 'mail_route'
                },
                {
                    'stripe_price': fulfillment_actual_price,
                    'tax_price': fulfillment_actual_price * 0.1,
                    'description': "头尾程：{}".format('-'.join(rp_ship_order_id.rp_ship_order_fulfillment_line_ids.mapped(lambda r: r.name))),
                    'type': 'fulfillment'
                },
                {
                    'stripe_price': value_added_actual_price,
                    'tax_price': value_added_actual_price * 0.1,
                    'description': "增值服务：{}".format('-'.join(rp_ship_order_id.rp_ship_order_value_added_line_ids.mapped(lambda r: r.value_added_id.name))),
                    'type': 'value_added'
                }
            ]
            rp_ship_order_payment_id.sudo().write({'state': 'not_pay'})  # 更新状态为未支付
            rp_ship_order_payment_id.sudo().write({'rp_payment_line_ids': [(5, 0, 0)]})
            rp_ship_order_payment_id.sudo().write({'rp_payment_line_ids': [(0, 0, value) for value in values]})
        return rp_ship_order_payment_id

    def geneate_invoice(self, pre_doc_ids, pre_doc_model_name):
        """
        开发票
        Params:
        -pre_doc_ids:支付单前置单据
        -pre_doc_model_name:前置单据的模型名称
        """
        rp_payments_ids = self.env['rp.payment'].search([('advance_document_id.field_record_id', 'in', pre_doc_ids)])  # 支付单
        pre_doc_record_ids = self.env[pre_doc_model_name].search([('id', 'in', pre_doc_ids)])  # 支付单前置单据
        # 生成前置单据记录
        pre_doc_ids = self.env['rp.related.model'].browse()
        for record in pre_doc_record_ids:
            pre_doc_id = self.env['rp.related.model'].create({'field_record_id': record.id, 'field_name_id': self.env['ir.model'].search([('model', '=', record._name)]).id})
            pre_doc_ids = pre_doc_ids | pre_doc_id
        if len(rp_payments_ids.ids) != len(pre_doc_record_ids.ids):
            raise UserError('支付单数量和相关的前置单据的数量不一致，支付单生成有误，请核对后重试！')
        # 生成发票
        values = {
            # 购买方
            'purchaser_name': "{}".format(pre_doc_record_ids[0].customer_id.name),
            'purchaser_address': "{}-{}-{}-{}".format(pre_doc_record_ids[0].invoice_state_id.name, pre_doc_record_ids[0].invoice_city_id.name, pre_doc_record_ids[0].invoice_receive_street,
                                                      pre_doc_record_ids[0].invoice_receive_street2 if pre_doc_record_ids[0].invoice_receive_street2 else '未指定'),
            'purchaser_address_type': pre_doc_record_ids[0].invoice_address_type,
            'purchaser_phone_number': pre_doc_record_ids[0].invoice_phone_number,
            'payment_record_ids': [(6, 0, rp_payments_ids.ids)],
            'advanced_document_ids': [(6, 0, pre_doc_ids.ids)],
            'payer_name': 'Palmnet',
            'payer_address': '西班牙（巴塞罗那）',
            'payer_address_type': 'commercial',
            'payer_phone_number': '13370895148'
        }
        order_invoice_id = self.env['rp.finance.invoice'].create(values)
        values_list = []
        # 填充发票明细
        for record in rp_payments_ids:
            payment_line_ids = record.rp_payment_line_ids
            for item in payment_line_ids:
                value = {
                    'description': item.description,
                    'type': item.type,
                    'amount_price': item.stripe_price,
                    'tax_rate': 0.1,
                    'tax_amount': item.tax_price,
                }
                values_list.append(value)
        order_invoice_id.write({'rp_finance_invoice_ids': [(0, 0, value) for value in values_list]})
        return rp_payments_ids

    def sql_get_act_window_id(self, model_name):
        """
        通过模型名获取窗口动作ID
        Params:
        -model_name: 模型名
        """
        try:
            # 通过模型名获取窗口动作的ID
            sql_id = "select id from ir_act_window " \
                     "where res_model ='{0}' ".format(model_name)
            self.env.cr.execute(sql_id)  # 执行sql语句
            rec_id = self.env.cr.dictfetchall()  # 获取sql的查询结果
            # 通过ID获取当前模型ir.action.act_window的名称
            sql_act = "select id,name,module from ir_model_data " \
                      "where res_id = '{0}' " \
                      "and model = 'ir.actions.act_window' " \
                      "order by id DESC".format(rec_id[0]['id'])  # 倒序排序，取第一条名称
            self.env.cr.execute(sql_act)  # 执行sql语句
            rec_act = self.env.cr.dictfetchall()  # 获取sql的查询结果
            return rec_act[0]['name'], rec_act[0]['module']
        except Exception as e:
            raise UserError("SQL_Error_0118:获取窗口动作ID,请及时联系管理员")

    def _get_form_view(self, res_model):
        """
        获取对应模型的视图
        Params：
        -res_model:模型名称
        """
        view_list = self.env['ir.ui.view'].search([('model', '=', res_model)])
        view_pos = ''
        for view in view_list:
            if view.name.rfind('Form') != -1:  # 如果可以模糊查询到form
                view_pos = view.xml_id
                break
        if view_pos != '':
            return view_pos
        else:
            raise UserError("Search_Error_0401:获取对应模型的视图,请及时联系管理员")

    def _get_tree_view(self, res_model):
        """
        获取对应模型的视图
        Params：
        -res_model:模型名称
        """
        view_list = self.env['ir.ui.view'].search([('model', '=', res_model)])
        view_pos = ''
        for view in view_list:
            if view.name.rfind('Tree') != -1:  # 如果可以模糊查询到form
                view_pos = view.xml_id
                break
        if view_pos != '':
            return view_pos
        else:
            raise UserError("Search_Error_0401:获取对应模型的视图,请及时联系管理员")

    def forward_to_upstream_form(self, upstream_id):
        """
        根据rp_related_model_id得到视图
        Params:
        -upstream_id:rp.related.model的模型ID
        """
        res_model = upstream_id.field_name_id.model
        rec_act, rec_module = self.sql_get_act_window_id(res_model)
        action_name = str(rec_module) + '.' + str(rec_act)
        action = self.env.ref(action_name)
        result = action.read()[0]
        result['type'] = 'ir.actions.act_window'
        result['view_type'] = 'form'
        result['view_mode'] = 'form'
        result['flags'] = {'initial_mode': 'view', 'action_buttons': False}
        view_name = str(self._get_form_view(res_model))
        res = self.env.ref(view_name)
        result['views'] = [(res.id, 'form')]
        result['res_id'] = upstream_id.field_record_id
        return result

    def forward_to_upstream_tree(self, upstream_ids):
        """
        获取Tree视图的方法
        Params:
        -upstream_ids:rp.related.model的模型ids
        """
        res_model = upstream_ids[0].field_name_id.model
        rec_act, rec_module = self.sql_get_act_window_id(res_model)
        action_name = str(rec_module) + '.' + str(rec_act)
        action = self.env.ref(action_name)
        result = action.read()[0]
        result['type'] = 'ir.actions.act_window'
        result['view_type'] = 'tree'
        result['view_mode'] = 'tree'
        result['flags'] = {'initial_mode': 'view', 'action_buttons': False}
        tree_view = str(self._get_tree_view(res_model))
        form_view = str(self._get_form_view(res_model))
        res_tree = self.env.ref(tree_view)
        res_form = self.env.ref(form_view)
        result['views'] = [(res_tree.id, 'tree'), (res_form.id, 'form')]
        result['context'] = {'delete': False, 'create': False, 'edit': False}
        result['domain'] = [('id', 'in', seq(upstream_ids).map(lambda r: r.field_record_id).to_list())]
        return result


    def stripe_pay(self, pay_price, request, way, payment_code):
        """
        Description：Stripe支付
        Params:
        -pay_price:支付金额
        -request:Odoo的请求对象
        -way:方式【odoo,qr_code】
        -payment_code:支付单编码
        """
        cookie = request.httprequest.headers.get('Cookie')
        params = '?cookie={}&way={}&payment_code={}'.format(cookie, way, payment_code)
        pay_url = RpPayInterface(self.env).action_to_pay(strategy='Stripe', pay_price=pay_price, params=params, success_basic_path='/order/check/success', error_basic_path='/order/check/fail')
        return pay_url
